package ModelAndController;
/*
 * A Model osztály a Model-View-Controller paradigma egyik alappilléreként 
 * az ütemezést, a hálózati elemek tárolását, valamint a hibakezelést 
 * megvalósító osztályokat tartalmazza és felügyeli a helyes működésüket.
 */
public class Model {
	//Az ütemező példánya.
	Scheduler scheduler;
	//Építőelemeket kezelő osztály példánya.
	CircuitElements circuitElements;
	//a hibakezelő osztály
	ExceptionHandler exceptionHandler;
	//az osztály üzeneteit tartalmazó tömb
	private String buffer;
	//maximum ciklusszám alapértelmezettje
	private int nbOfMaxUpdates=100;
	//soremelés karaktert tartalmazó string
	private String newLine;
	/*
	 * Létrehozza az A-E hálózatot a nbOfCircuitType paraméter alapján.
	 */
	public Model(){	
		exceptionHandler = new ExceptionHandler();
		newLine = System.getProperty("line.separator");
	}
	//az alapértelmezett maximum ciklusszámot adja vissza
	public int getNbOfMaxUpdates() {
		return nbOfMaxUpdates;
	}
	//visszaadja,hogy be lett-e már töltve a hálózat
	public boolean isCircuitLoaded(){
		if( circuitElements == null )
			return false;
		return true;
	}
	//a maximális ciklusszámot állítja be
	public void setNbOfMaxUpdates(int copyNbOfMaxUpdates) {
		boolean valideSet = true;
		buffer = "";
		if(circuitElements != null){
			valideSet = false;
			buffer = "Limit ONLY can be set before loading circuit!";
		}
		if( copyNbOfMaxUpdates < 1){
			valideSet = false;
			buffer = "Scheduler limit must be greather then 0!";
		}
		if( valideSet ){
			nbOfMaxUpdates = copyNbOfMaxUpdates;
			buffer = "Sceduler limit is "+nbOfMaxUpdates;
		}
	}
	//hálózat beolvasása fájlból
	public void readFromFile(String fileName) throws Exception{
		ReadCircuitFromFile readFile = new ReadCircuitFromFile(0);
		try{
			circuitElements = readFile.readInCircuit(fileName, nbOfMaxUpdates);
			scheduler=new Scheduler(circuitElements);
			scheduler.setNbOfMaxUpdates(nbOfMaxUpdates);
			
			buffer = "Created circuit from "+fileName;
		}
		catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
	}
	//ütemező függvény indítása
	public void schedule(int nbOfSteps) throws Exception{
		buffer = "";
		try{
			if( circuitElements == null){
				buffer = "Invalid command, no circuit loaded!";
				return;
			}
			if( nbOfSteps < 1){
				buffer = "Number of schedule steps should be greater than 0!";
				return;
			}
			try{
				for(int act=0; act<nbOfSteps; act++)
					startSchedule(false, null);
				buffer = scheduler.getBuffer();
			}catch(Exception e){
				buffer = exceptionHandler.reactToException(e);
			}
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
	}
	//Indítja az ütemezési ciklust.  
	public void startSchedule(boolean shouldListDetails, int[] compositeElementsToList) throws Exception{
		buffer = "";
		try{
			if( circuitElements == null){
				buffer = "Invalid command, no circuit loaded!";
				return;
			}
			try{
				scheduler.isUpdateResultStableCircuit(shouldListDetails, compositeElementsToList);
				buffer = scheduler.getBuffer();
			
			}catch(Exception e){
				buffer = exceptionHandler.reactToException(e);
			}
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
	}
	// Visszaadja a kapcsolók számát.
	public int getNbOfSwitches(){
		return circuitElements.getNbOfSwitches();
	}
	// Visszaadja az actSwitch sorszámu Switch állapotát.
	public int getValueOfActualSwitch(int actSwitch) {
		return circuitElements.getValueOfActualSwitch(actSwitch);
	}
	//az összes kalcsoló értékét visszaadja
	public int[] getAllValueOfSwitches() throws Exception{
		buffer = "";
		int[] retValue = null;
		
		try{
			if( circuitElements == null ){
				buffer = "Invalid command, no circuit loaded!";
				return retValue;
			}
			if( getNbOfSwitches() == 0){
				buffer = "No switch in circuit!";
				return retValue;
			}
			retValue = new int[getNbOfSwitches()];
			for(int act=0; act<getNbOfSwitches(); act++){
				retValue[act] = getValueOfActualSwitch(act);
				if( act != (getNbOfSwitches()-1) )
					buffer = buffer.concat(act+" Switch "+getValueOfActualSwitch(act)+newLine);
				else
					buffer = buffer.concat(act+" Switch "+getValueOfActualSwitch(act));
			}
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
		return retValue;
	}
	// Átállitja az actSwitch sorszámu Switch belső állapotát.
	public void setValueOfActualSwitch(int actSwitch)  throws Exception{
		buffer = "";
		try{
			if( circuitElements == null ){
				buffer = "Invalid command, no circuit loaded!";
				return;
			}
			int nbOfSwitches = getNbOfSwitches();
			if( actSwitch < 0 || nbOfSwitches<= actSwitch){
				buffer = "No switch with ID="+actSwitch;
				return;
			}
			else{
				circuitElements.setValueOfActualSwitch(actSwitch);
				buffer = "Switch with ID="+actSwitch+", new value: "+getValueOfActualSwitch(actSwitch);
			}
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
	}
	//Visszaadja a jelgenerátorok számát.
	public int getNbOfSignalGenerators(){
		return circuitElements.getNbOfSignalGenerators();
	}
	public int[] getActValuesOfSignals() throws Exception{
		int[] retValue = new int[getNbOfSignalGenerators()];
		
		for(int act=0; act<retValue.length; act++)
			retValue[act] = circuitElements.getValueOfActualSignalGenerator(act);
		
		return retValue;
	}
	//az összes jelgenerátor értékét visszaadja
	public int[][] getAllValueOfSignals() throws Exception{
		buffer = "";
		int[][] retValue = null;
		
		try{
			if( circuitElements == null){
				buffer = "Invalid command, no circuit loaded!";
				return retValue;
			}
		
			if( getNbOfSignalGenerators() == 0){
				buffer = "No signalGenerator in circuit!";
				return retValue;
			}
			retValue = new int[getNbOfSignalGenerators()][];
			for(int act=0; act<getNbOfSignalGenerators(); act++){
				buffer = buffer.concat(act+" SignalGenerator ");
				int[] actValue = getValuesOfActualSignalGenerator(act);
				retValue[act] = actValue.clone();
				for(int actV=0; actV<actValue.length; actV++){
					buffer = buffer.concat( Integer.toString(actValue[actV]) );
					if( actV != (actValue.length-1) )
						buffer = buffer.concat(" ");
				}
				if( act != (getNbOfSignalGenerators()-1) )
					buffer = buffer.concat(newLine);
			}
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
		return retValue;
	}
	// Az actSignalG sorszámú SignalGenerator int tömbjét állítja be az int[] values alapján.
	public void setValuesOfActualSignalGenerator(int actSignalG, int[] values)  throws Exception{
		buffer = "";
		try{
			if( circuitElements == null ){
				buffer = "Invalid command, no circuit loaded!";
				return;
			}
		
			if( actSignalG <0 || getNbOfSignalGenerators() <= actSignalG){
				buffer = "No signalGenerator with ID="+actSignalG;
				return;
			}
			circuitElements.setValuesOfActualSignalGenerator(actSignalG, values);
			buffer = "SignalGenerator with ID="+actSignalG+", new value: ";
			for(int act=0; act<values.length; act++){
				buffer = buffer.concat(Integer.toString(values[act])+" ");
			}
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
	}
	//az aktuális jelgenerátor értékeit adja vissza
	public int[] getValuesOfActualSignalGenerator(int actSignalG) {
		return circuitElements.getValuesOfActualSignalGenerator(actSignalG);
	}
	//az összes scope értékét adja vissza
	public int[][] getAllScope() throws Exception{
		buffer = "";
		int retValue[][] = null;
		
		try{
			if( circuitElements == null ){
				buffer = "Invalid command, no circuit loaded!";
				return retValue;
			}
		
			if( getNbOfScopes() == 0){
				buffer = "No scope in the circuit!";
				return retValue;
			}
			retValue = new int[getNbOfScopes()][];
			for(int act=0; act<getNbOfScopes(); act++){
				buffer = buffer.concat(act+" Scope ");
				int[] values = getValuesOfActualScope(act);
				retValue[act] = values.clone();
				for(int actV=0; actV<values.length; actV++)
					buffer = buffer.concat(values[actV]+" ");
				buffer = buffer.concat(newLine);
			}
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
		return retValue;
	}
	
	//Az osszes scope delta erteket adja vissza
	public int[][] getAllDeltaValueOfScopes(){
		int[][] retValue = null;
		
		if( circuitElements == null )
			return retValue;
	
		if( getNbOfScopes() == 0)
			return retValue;
		
		retValue = new int[getNbOfScopes()][];
		for(int act=0; act<retValue.length; act++)
			retValue[act] = getDeltaOfActualScope(act);
		
		return retValue;
	}
	//Az adott scope stabil allapotait adja vissza.
	public void getActualScope(int scopeIndex ) throws Exception{
		buffer = "";
		try{
			if( circuitElements == null ){
				buffer = "Invalid command, no circuit loaded!";
				return;
			}
			if( scopeIndex < 0 || getNbOfScopes() <= scopeIndex ){
				buffer = "No scope with ID="+scopeIndex;
				return;
			}
			int[] deltaValues = getDeltaOfActualScope( scopeIndex );
			buffer = "Scope with ID="+scopeIndex+" unstable values: ";
			for(int act=0; act<deltaValues.length; act++)
				buffer = buffer.concat(deltaValues[act]+" ");
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
	}
	//az aktuális scope értékét adja vissza
	public int[] getValuesOfActualScope(int actScope) {
		return circuitElements.getValuesOfActualScope(actScope);
	}
	//az aktuális scope deltáját adja vissza
	public int[] getDeltaOfActualScope(int actScope) {
		return circuitElements.getDeltaOfActualScope(actScope);
	}
	//a scope-ok számát adja vissza
	public int getNbOfScopes(){
		return circuitElements.getNbOfScopes();
	}
	//a kijelzők számát adja vissza
	public int getNbOfDisplays(){
		return circuitElements.getNbOfDisplays();
	}
	//Visszaadja a display-ek allapotat.
	public int[] getAllDisplay() throws Exception{
		buffer = "";
		int[] retValue = null;
		
		try{
			if( circuitElements == null ){
				buffer = "Invalid command, no circuit loaded!";
				return retValue;
			}
			if( getNbOfDisplays() == 0){
				buffer = "No display in circuit!";
				return retValue;
			}
			retValue = new int[getNbOfDisplays()];
			for(int act=0; act<getNbOfDisplays(); act++){
				retValue[act] = getValueOfActualDisplay(act);
				buffer = buffer.concat(act+" Display "+getValueOfActualDisplay(act));
				if( act!= getNbOfDisplays()-1 )
					buffer = buffer.concat(newLine);		
			}
		}catch(Exception e){
			buffer = exceptionHandler.reactToException(e);
		}
		return retValue;
	}
	//az aktuális kijelző értékét adja vissza
	public int getValueOfActualDisplay(int actDisplay) {
		return circuitElements.getValueOfActualDisplay(actDisplay);
	}	
	/**
	 * @return the buffer
	 */
	public String getBuffer() {
		return buffer;
	}
	/**
	 * @param buffer the buffer to set
	 */
	public void setBuffer(String buffer) {
		this.buffer = buffer;
	}
}